package gameTheory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import model.Route;
import graphs.Graph;

public class MixedProfileGenerator extends ProfileGenerator {

	public static int resolution = 4;
	private int nbPositions;

	public MixedProfileGenerator(Graph g){
		super(g);
		assert(nbPositions>0);
	}

	protected void createProfiles(Graph g) {
		Set<Route> routes = g.getAllRoutes();
		nbPositions = routes.size();

		Iterator<Route> itt;

		List<double[]> strategyProbs = new ArrayList<double[]>();
		fillStrategyProbs(strategyProbs);

		for (double[] probs : strategyProbs) {
			Map<Route,Double> routeProb = new HashMap<Route,Double>();
			itt = routes.iterator();

			for(int i = 0 ; i < probs.length ; i++)
				routeProb.put(itt.next(), probs[i]);

			assert !itt.hasNext();

			player.add(new Strategy(routeProb));
			others.add(new Strategy(routeProb));
		}

		for(Strategy ps : player){
			for(Strategy os : others)
				profiles.add(new Profile(ps,os,g));
		}
	}

	/*public void fillStrategyProbs(List<Double[]> strategy, Integer[] part, int rest, int position){
		assert(nbPositions>0);

		if(position < nbPositions){
			int start = 0;
			if(position == (nbPositions - 1))
				start = rest;
			for(int i = start ; i <= rest ; i++){
				part[position] = i;
				fillStrategyProbs(strategy, part, rest-i, position+1);
			}
		} else {
			Double[] strat = new Double[nbPositions];
			for (int i = 0 ; i < nbPositions ; i++)
				strat[i] = (1.0*part[i])/(resolution*nbPositions);
			strategy.add(strat);
		}
	}*/

	public void fillStrategyProbs(List<double[]> strategy){
		assert(nbPositions>0);

		int last = nbPositions - 1;
		Integer[] part = new Integer[nbPositions];
		Integer[] rest = new Integer[nbPositions];

		final int maxRest = nbPositions * resolution;
		for(int i = 0 ; i < nbPositions ; i++){
			rest[i] = maxRest;
			part[i] = 0;
		}

		do{
			part[last] = rest[last];
			
			double[] strat = new double[nbPositions];
			for (int i = 0 ; i < nbPositions ; i++)
				strat[i] = (1.0*part[i])/(maxRest);
			strategy.add(strat);
			
		}while(increase(part, rest, last-1));
	}

	private boolean increase(Integer[] part, Integer[] rest, int position) {
		if(position<0)
			return false;
		
		boolean result = true;
		if(part[position] < rest[position]) {
			part[position]++;
		}else{
			result = increase(part,rest,position-1);
			part[position] = 0;
		}
		rest[position+1] = rest[position] - part[position];
		return result;
	}
}
